# file:: container.rb
# author::  Ralph M. Churchill
# version::
# date::
#
# This source code copyright (C) 2006 by Ralph M. Churchill
# All rights reserved.
#
# Released under the terms of the GNU General Public License
# See LICENSE file for additional information.

require 'models/entity'
require 'database/game_database'

module BelongsToAccount
    properties :account_id
    def account
        AccountDatabase.instance.get(self.account_id)
    end
    def account=(a)
        raise "Not a valid Account!" unless a.respond_to?(:oid)
        self.account_id=a.oid
    end
end

module BelongsToRoom
    properties :room_id
    def room
        RoomDatabase.instance.get(self.room_id)
    end
    def room=(r)
        raise "Not a valid Room!" unless r.respond_to?(:oid)
        self.remove_from_room(self.room) if self.room_id
        self.room_id = r.oid
        self.add_to_room(r) 
    end
    def remove_from_room(room)
        func = "del_#{self.class.to_s.downcase}"
        room.send(func,self) if room.respond_to?(func)
    end
    def add_to_room(room)
        func = "add_#{self.class.to_s.downcase}"
        room.send(func,self) if room.respond_to?(func)
    end
end

module BelongsToRegion
    properties :region_id
    def region
        RegionDatabase.instance.get(self.region_id)
    end
    def region=(r)
        raise "Not a valid Region!" unless r.respond_to?(:oid)
        self.remove_from_region(self.region) if self.region_id
        self.region_id=r.oid
        self.add_to_region(r)
    end
    def remove_from_region(region)
        func = "del_#{self.class.to_s.downcase}"
        region.send(func,self) if region.respond_to?(func)
    end
    def add_to_region(region)
        func = "add_#{self.class.to_s.downcase}"
        region.send(func,self) if region.respond_to?(func)
    end
end
module BelongsToCharacter
    properties :character_id
    def character
        CharacterDatabase.instance.get(self.character_id)
    end
    def character=(r)
        raise "Not a valid Character!" unless r.respond_to?(:oid)
        self.remove_from_character(self.character) if self.character_id
        self.character_id=r.oid
        self.add_to_character(r)
    end
    def remove_from_character(character)
        func = "del_#{self.class.to_s.downcase}"
        character.send(func,self) if character.respond_to?(func)
    end
    def add_to_character(character)
        func = "add_#{self.class.to_s.downcase}"
        character.send(func,self) if character.respond_to?(func)
    end
end
module HasManyCharacters
    properties :has_characters
    def add_character(c)
        raise "Cannot add character #{c} to #{self}!" unless c.respond_to?(:oid)
        self.has_characters ||= []
        self.has_characters |= [c.oid]
    end
    def del_character(c)
        self.has_characters ||= []
        self.has_characters.delete(c.oid)
    end
    def characters
        self.has_characters ||= []
        self.has_characters.collect{|c| CharacterDatabase.instance.get(c)}.compact
    end
end

module HasManyItems
    properties :has_items
    def add_item(c)
        raise "Cannot add item #{c} to #{self}!" unless c.respond_to?(:oid)
        self.has_items ||= []
        self.has_items |= [c.oid]
    end
    def del_item(c)
        self.has_items ||= []
        self.has_items.delete(c.oid)
    end
    def items
        self.has_items ||= []
        self.has_items.collect{|c| ItemDatabase.instance.get(c)}.compact
    end
end

module HasManyRooms
    properties :has_rooms
    def add_room(c)
        raise "Cannot add room #{c} to #{self}!" unless c.respond_to?(:oid)
        self.has_rooms ||= []
        self.has_rooms |= [c.oid]
    end
    def del_room(c)
        self.has_rooms ||= []
        self.has_rooms.delete(c.oid)
    end
    def rooms
        self.has_rooms ||= []
        self.has_rooms.collect{|c| RoomDatabase.instance.get(c)}.compact
    end
end

module HasManyPortals
    properties :has_portals
    def add_portal(c)
        raise "Cannot add portal #{c} to #{self}!" unless c.respond_to?(:oid)
        self.has_portals ||= []
        self.has_portals |= [c.oid]
    end
    def del_portal(c)
        self.has_portals ||= []
        self.has_portals.delete(c.oid)
    end
    def portals
        self.has_portals ||= []
        self.has_portals.collect{|c| PortalDatabase.instance.get(c)}.compact
    end
end

# Actions and Logic are "owned" by Entities. Any type of supported Entity
# can own an Action or Logic - the Action/Logic doesn't know or care what
# type of Entity it is or where it is stored.
module BelongsToEntity
    properties :owner_type,:owner_oid

    VALID_OWNER_MAPPINGS = {
        :Character => CharacterDatabase.instance,
        :Room => RoomDatabase.instance,
        :Item => ItemDatabase.instance,
        :Portal => PortalDatabase.instance,
        :Region => RegionDatabase.instance
    }

    def owner=(o)
        raise "#{o} is not an Entity!" unless o.respond_to?(:oid)
        raise "#{o} is missing an ID!" if o.oid.nil?
        self.owner_type = o.class.name.to_sym
        raise "Don't know how to belong to an entity of type: #{o.class}" unless \
            VALID_OWNER_MAPPINGS.keys.include?(self.owner_type)
        self.owner_oid = o.oid
    end
    def owner
        VALID_OWNER_MAPPINGS[self.owner_type].get(self.owner_oid)
    end
end
